package com.neusoft.hifly.lock;

import org.redisson.Redisson;
import org.redisson.config.Config;

import com.google.common.base.Preconditions;

import com.neusoft.hifly.lock.config.RedissonConfig;
import com.neusoft.hifly.lock.constant.RedisConnectionType;
import com.neusoft.hifly.lock.strategy.RedissonConfigService;
import com.neusoft.hifly.lock.strategy.impl.ClusterConfigImpl;
import com.neusoft.hifly.lock.strategy.impl.MasterslaveConfigImpl;
import com.neusoft.hifly.lock.strategy.impl.SentineConfigImpl;
import com.neusoft.hifly.lock.strategy.impl.StandaloneConfigImpl;
import com.neusoft.hifly.lock.utils.Log;

/**
 * Redisson核心配置，用于提供初始化的redisson实例
 */
public class RedissonManager {

	private Config config = new Config();

	private Redisson redisson = null;

	public RedissonManager() {
	}

	public RedissonManager(final RedissonConfig redissonProperties) {
		try {
			//通过不同部署方式获得不同cofig实体
			config = RedissonConfigFactory.getInstance().createConfig(redissonProperties);
			redisson = (Redisson) Redisson.create(config);
		} catch (final Exception e) {
			Log.error("Redisson init error", e);
			throw new IllegalArgumentException("please input correct configurations,"
					+ "connectionType must in standalone/sentinel/cluster/masterslave");
		}
	}

	public Redisson getRedisson() {
		return redisson;
	}

	/**
	 * Redisson连接方式配置工厂 双重检查锁
	 */
	static class RedissonConfigFactory {

		private RedissonConfigFactory() {
		}

		private static volatile RedissonConfigFactory factory = null;

		public static RedissonConfigFactory getInstance() {
			if (RedissonConfigFactory.factory == null) {
				synchronized (Object.class) {
					if (RedissonConfigFactory.factory == null) {
						RedissonConfigFactory.factory = new RedissonConfigFactory();
					}
				}
			}
			return RedissonConfigFactory.factory;
		}

		/**
		 * 根据连接类型获取对应连接方式的配置,基于策略模式
		 *
		 * @param redissonProperties
		 *            redis连接信息
		 * @return Config
		 */
		Config createConfig(final RedissonConfig redissonProperties) {
			Preconditions.checkNotNull(redissonProperties);
			Preconditions.checkNotNull(redissonProperties.getAddress(), "redisson.lock.server.address cannot be NULL!");
			Preconditions.checkNotNull(redissonProperties.getType(), "redisson.lock.server.password cannot be NULL");
			Preconditions.checkNotNull(redissonProperties.getDatabase(),
					"redisson.lock.server.database cannot be NULL");
			final String connectionType = redissonProperties.getType();
			//声明配置上下文
			RedissonConfigService redissonConfigService = null;
			if (connectionType.equalsIgnoreCase(RedisConnectionType.STANDALONE.getConnectionType())) {
				redissonConfigService = new StandaloneConfigImpl();
			} else if (connectionType.equalsIgnoreCase(RedisConnectionType.SENTINEL.getConnectionType())) {
				redissonConfigService = new SentineConfigImpl();
			} else if (connectionType.equalsIgnoreCase(RedisConnectionType.CLUSTER.getConnectionType())) {
				redissonConfigService = new ClusterConfigImpl();
			} else if (connectionType.equalsIgnoreCase(RedisConnectionType.MASTERSLAVE.getConnectionType())) {
				redissonConfigService = new MasterslaveConfigImpl();
			} else {
				throw new IllegalArgumentException("创建Redisson连接Config失败！当前连接方式:" + connectionType);
			}
			return redissonConfigService.createRedissonConfig(redissonProperties);
		}
	}

}
